package my.syncfilter.entity;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.annotation.JSONField;
import org.apache.commons.lang3.StringUtils;
import my.syncfilter.CommonUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * 话单配置
 */
public class BillConfig {
    /**
     * 默认sql
     */
    private static String DEFAULT_SQL = "SELECT ${billFields} FROM ${tableName} ";

    // 配置前缀
    private String prefix;

    //导出数据时间
    private String exportTime;

    //导出类型
    private String exportType;

    //本机ip
    private String ip;

    //数据表id
    private int id;

    //运行时查询的数据总量(用于统计数据总量，计算进度等)
    private int queryTotal;

    private String querySql;
    private String tableName;
    private int pageSize;
    private int queryStart;
    private String fieldSplitStr;
    private String lineSplitStr;
    private String partitions;
    private String billFields;

    @JSONField(serialize=false)
    private List<String> billFieldList;

    private String filePrefixName;
    private String fileSuffixName;
    private int fileMaxLine;
    private int fileMaxSize;
    private String fileCharsetName;
    private String sumFileName;
    private String fileBasePath;

    private String uploadType;
    private String uploadDel;
    private String uploadDirectory;

    // 过滤配置
    private String expressionRule;
    private String expressionField;
    private String expressionFieldType;
    private String expressionValue;

    private String cronExpression;
    private String jsonField;
    private List<SplitUser> split;
    private String dataSource;
    private String userName;
    private String channelCapacity;
    //是否压缩文件默认不压缩 0
    private String  compressed;
    //文件备份地址
    private String fileBackupBasePath;

    private String conditionField;
    private FieldType conditionType;

    private String segmentReg;
    private String segmentField;

    private String ignoreTotal;

    // Utc转换相关
    private String utcFields;
    private String utcEXT;

    private String conditionPath;

    private static String rootPath = System.getProperty("user.home");

    private BillConfig() { }

    public String getChannelCapacity() {
        return channelCapacity;
    }

    public void setChannelCapacity(String channelCapacity) {
        this.channelCapacity = channelCapacity;
    }

    public String getFileBackupBasePath() {
        return fileBackupBasePath;
    }

    public void setFileBackupBasePath(String fileBackupBasePath) {
        this.fileBackupBasePath = fileBackupBasePath;
    }

    /**
     * 构造器
     *
     * @param prefix
     */
    public BillConfig(String prefix, Properties properties) {
        this.prefix = prefix;

        this.setTableName(CommonUtils.getProperties(properties,"tableName"));
        this.setExportTime(CommonUtils.getProperties(properties,"exportTime"));
        this.setExportType(CommonUtils.getProperties(properties,"exportType", "FULL"));
        this.setPageSize(Integer.parseInt(CommonUtils.getProperties(properties,"pageSize", "500")));
        this.setQueryStart(Integer.parseInt(CommonUtils.getProperties(properties,"queryStart", "0")));
        this.setFieldSplitStr(CommonUtils.getProperties(properties,"fieldSplitStr", "|"));
        this.setLineSplitStr(CommonUtils.getProperties(properties,"lineSplitStr", "\r\n"));
        this.setPartitions(CommonUtils.getProperties(properties,"partitions"));
        this.setQuerySql(CommonUtils.getProperties(properties,"querySql"));
        this.setBillFields(CommonUtils.getProperties(properties,"billFields","").toUpperCase());
        this.setBillFieldList(strToList(getBillFields()));
        this.setFilePrefixName(CommonUtils.getProperties(properties,"filePrefixName",getTableName()+"{$DATE:yyyyMMddHHmmssSSS}_%S_{$RANDOM:0001}"));
        this.setFileSuffixName(CommonUtils.getProperties(properties,"fileSuffixName","txt"));
        this.setFileMaxLine(Integer.parseInt(CommonUtils.getProperties(properties,"fileMaxLine", "1000000")));
        this.setFileMaxSize(Integer.parseInt(CommonUtils.getProperties(properties,"fileMaxSize", "0")));
        this.setFileCharsetName(CommonUtils.getProperties(properties,"fileCharsetName", "UTF-8"));
        this.setFileBasePath(CommonUtils.getProperties(properties,"fileBasePath", rootPath+"/data/")
                +getExportType() +"/" +getExportTime()+"/"+getTableName()+"/") ;
        this.setSumFileName(CommonUtils.getProperties(properties,"sumFileName",getTableName()+"{$DATE:yyyyMMddHHmmssSSS}_%S_SUM"));
        this.setUploadType(CommonUtils.getProperties(properties,"uploadType","1"));
        this.setUploadDel(CommonUtils.getProperties(properties,"uploadDel","1"));
        this.setUploadDirectory(CommonUtils.getProperties(properties,"uploadDirectory","/migu_sm/")
                +getExportType() +"/" +getExportTime()+"/"+getTableName());
        this.setCronExpression(CommonUtils.getProperties(properties,"cronExpression"));
        this.setJsonField(CommonUtils.getProperties(properties,"jsonFiled"));
        this.setSplit4json(CommonUtils.getProperties(properties,"split"));
        this.setDataSource(CommonUtils.getProperties(properties,"dataSource"));
        this.setUserName(CommonUtils.getProperties(properties,"userName"));
        this.setChannelCapacity(CommonUtils.getProperties(properties,"channelCapacity","1000"));
        this.setCompressed(CommonUtils.getProperties(properties,"compressed","1"));
        this.setFileBackupBasePath(CommonUtils.getProperties(properties,"fileBackupBasePath",""));
        // 配置过滤条件
        this.setExpressionRule(CommonUtils.getProperties(properties,"expressionRule"));
        String expression = CommonUtils.getProperties(properties,"expressionField");

        this.setExpressionValue(CommonUtils.getProperties(properties,"expressionValue"));
        this.setIp(CommonUtils.getProperties(properties,"ip",""));
        // utc转换
        this.setUtcFields(CommonUtils.getProperties(properties,"utcFields"));
        this.setUtcEXT(CommonUtils.getProperties(properties,"utcEXT"));
        // 总数据量统计
        this.setQueryTotal(Integer.parseInt(CommonUtils.getProperties(properties,"queryTotal","0")));
        // 未配置sql时，自动创建sql
        if (null!=getQuerySql()) {
            this.buildQuerySql();
        }

        String condition = CommonUtils.getProperties(properties, "conditionField", "");
        if (null!=condition)
        {
            try
            {
                this.setConditionType(FieldType.get(condition));
            }
            catch (Exception e)
            {
                // 此处配置参数异常，则服务终止
                // System.exit(-1);
            }

        }

        this.setSegmentField(CommonUtils.getProperties(properties,"segmentField",""));
        this.setSegmentReg(CommonUtils.getProperties(properties,"segmentReg",""));

        this.setIgnoreTotal(CommonUtils.getProperties(properties,"ignoreTotal",""));

        this.setConditionPath(CommonUtils.getProperties(properties,"conditionPath",""));
    }

    private void setDataSource(String dataSource) {
        this.dataSource=dataSource;
    }

    public String getDataSource() {
        return dataSource;
    }

    private void setSplit4json(String split) {
        if(split==null || split.isEmpty()){
            return;
        }
        List<SplitUser> splitUser = JSON.parseObject(split, new TypeReference<List<SplitUser>>() { });
        this.split=splitUser;
    }


    public String getExportTime() {
        return exportTime;
    }

    public void setExportTime(String exportTime) {
        this.exportTime = exportTime;
    }

    public String getCompressed() {
        return compressed;
    }

    public void setCompressed(String compressed) {
        this.compressed = compressed;
    }

    public String getExportType() {
        return exportType;
    }

    public void setExportType(String exportType) {
        this.exportType = exportType;
    }

    public String getUploadDirectory() {
        return uploadDirectory;
    }

    public void setUploadDirectory(String uploadDirectory) {
        this.uploadDirectory = uploadDirectory;
    }

    public String getUploadType() {
        return uploadType;
    }

    public void setUploadType(String uploadType) {
        this.uploadType = uploadType;
    }


    public String getUploadDel() {
        return uploadDel;
    }

    public void setUploadDel(String uploadDel) {
        this.uploadDel = uploadDel;
    }

    public String getPrefix() {
        return prefix;
    }

    /**
     * 查询sql，querySql未配置时生成自动sql
     */
    public void buildQuerySql() {
        String sql = DEFAULT_SQL.replace("${billFields}", getBillFields()).replace("${tableName}", getTableName());
        //配置了分区
        /*if (!StringUtils.isEmpty(partitions)) {
            sql = sql.replace(tableName,tableName+" partition(${partition}) ");
        }*/
        this.querySql = sql;
    }

    public String getQuerySql() {
        return querySql;
    }

    public String getQuerySql4Partition(String partition) {

        if(!StringUtils.isEmpty(userName)){
            userName+=".";
        }else{
            userName="";
        }

        if (!StringUtils.isEmpty(partition)) {
            //替换分区
            return getQuerySql().replace(tableName, userName+tableName+" partition("+partition+") ");
        }else{
            //替换用户
            return getQuerySql().replace(tableName, userName+tableName);
        }
    }

    public String getQuerySql4Split(String splitUser,String splitTable,String partition) {
        StringBuilder sb=new StringBuilder();
        sb.append(userName);
        if(!StringUtils.isEmpty(splitUser)){
            sb.append(splitUser);
        }
        sb.append(".");
        sb.append(tableName);
        if(!StringUtils.isEmpty(splitTable)){
            sb.append(splitTable);
        }
        sb.append(" ");
        if(!StringUtils.isEmpty(partition)){
            sb.append("partition(");
            sb.append(partition);
            sb.append(") ");
        }
        //替换分区
        return getQuerySql().replace(tableName, sb.toString());
    }

    public String getQuerySql4Segment(String field,String start,String end) {

        String where = " where ";
        String column = CommonUtils.getExpField(field);
        if (FieldType.get(field) == FieldType.DATE) {
            //增加时间类型条件
            where = where + column + ">=to_date('" +  start+"','yyyyMMddHH24miss') and "+ column + "<to_date('" +  end+"','yyyyMMddHH24miss')";
        }else{
            //替换用户
            where = where + column + ">='" +start +"' and "+column +"<'"+end+"'";
        }

        String sql = getQuerySql();

        if (sql.toUpperCase().contains("WHERE"))
        {
            where = where +" and ";
            sql = sql.replace("WHERE", where);
        }
        else
        {
            where = getTableName() +" " + where;
            sql = sql.replace(getTableName(), where);
        }

        return sql;
    }

    public void setQuerySql(String sql) {
        //配置了默认分区
        /*if(!StringUtils.isEmpty(sql) && getPartitionList().size()>0)
        {
            this.querySql = sql.replace(tableName,tableName+" partition(${partition}) ");
            return;
        }*/

        this.querySql = sql;
    }

    public int getQueryStart() {
        return queryStart;
    }

    public void setQueryStart(int queryStart) {
        this.queryStart = queryStart;
    }

    public String getFieldSplitStr() {
        return fieldSplitStr;
    }

    public void setFieldSplitStr(String fieldSplitStr) {
        this.fieldSplitStr = fieldSplitStr;
    }

    public String getLineSplitStr() {
        return lineSplitStr;
    }

    public void setLineSplitStr(String lineSplitStr) {
        this.lineSplitStr = lineSplitStr;
    }

    public String getSumFileName() {
        return sumFileName;
    }

    public void setSumFileName(String sumFileName) {
        this.sumFileName = sumFileName;
    }

    /**
     * 分页数，可为空，默认0表示不分页
     *
     * @param pageSize
     */
    public void setPageSize(int pageSize) {
        this.pageSize = pageSize;
    }

    /**
     * 分区，可为空，默认不分区查询
     *
     * @param partitions
     */
    public void setPartitions(String partitions) {
        this.partitions = partitions;
    }

    /**
     * 话单字段，不可为空
     *
     * @param billFields
     */
    public void setBillFields(String billFields) {
        this.billFields = billFields;
    }

    /**
     * 话单文件前缀，可为空，默认：bill
     *
     * @param filePrefixName
     */
    public void setFilePrefixName(String filePrefixName) {
        this.filePrefixName = filePrefixName;
    }

    /**
     * 话单文件后缀，可为空，默认：txt
     *
     * @param fileSuffixName
     */
    public void setFileSuffixName(String fileSuffixName) {
        this.fileSuffixName = fileSuffixName;
    }

    /**
     * 话单文件最大行记录，可为空，表示不限制行记录
     *
     * @param fileMaxLine
     */
    public void setFileMaxLine(int fileMaxLine) {
        this.fileMaxLine = fileMaxLine;
    }

    /**
     * 话单文件大小，可为空，表示不限制文件大小
     *
     * @param fileMaxSize
     */
    public void setFileMaxSize(int fileMaxSize) {
        this.fileMaxSize = fileMaxSize;
    }

    public int getPageSize() {
        return pageSize;
    }

    public String getPartitions() {
        return partitions;
    }

    public String getBillFields() {
        return billFields;
    }

    public String getFilePrefixName() {
        return filePrefixName;
    }

    public String getFileSuffixName() {
        return fileSuffixName;
    }

    public int getFileMaxLine() {
        return fileMaxLine;
    }

    public int getFileMaxSize() {
        return fileMaxSize;
    }


    public List<String> getPartitionList() {
        return strToList(partitions);
    }

    private List<String> strToList(String str) {
        if (StringUtils.isEmpty(str)) {
            return new ArrayList<>();
        }
        return null;//Splitter.on(",").trimResults().splitToList(str);
    }

    /**
     * 创建配置
     *
     * @param prefix
     * @return
     */
    public static BillConfig factory(String prefix, Properties properties) {
        return new BillConfig(prefix, properties);
    }

    public String getTableName() {
        return tableName;
    }

    public void setTableName(String tableName) {
        this.tableName = tableName;
    }

    public String getFileCharsetName() {
        return fileCharsetName;
    }

    public void setFileCharsetName(String fileCharsetName) {
        this.fileCharsetName = fileCharsetName;
    }

    public String getFileBasePath() {
        return fileBasePath;
    }

    public void setFileBasePath(String fileBasePath) {
        this.fileBasePath = fileBasePath;
    }


    public String getExpressionRule() {
        return expressionRule;
    }

    public void setExpressionRule(String expressionRule) {
        this.expressionRule = expressionRule;
    }

    public String getExpressionField() {
        return expressionField;
    }

    public void setExpressionField(String expressionField) {
        this.expressionField = expressionField;
    }

    public String getExpressionFieldType() {
        return expressionFieldType;
    }

    public void setExpressionFieldType(String expressionFieldType) {
        this.expressionFieldType = expressionFieldType;
    }

    public String getExpressionValue() {
        return expressionValue;
    }

    public void setExpressionValue(String expressionValue) {
        this.expressionValue = expressionValue;
    }

    public String getCronExpression()
    {
        return cronExpression;
    }

    public void setCronExpression(String cronExpression)
    {
        this.cronExpression = cronExpression;
    }


    public String getJsonField()
    {
        return jsonField;
    }

    public void setJsonField(String jsonField)
    {
        this.jsonField = jsonField;
    }


    public void setUserName(String userName){
        this.userName=userName;
    }

    public String getUserName(){
        return this.userName;
    }

    public List<SplitUser> getSplit() {
        return split;
    }

    public void setSplit(List<SplitUser> split) {
        this.split = split;
    }

    public String getConditionField() {
        return conditionField;
    }

    public void setConditionField(String conditionField) {
        this.conditionField = conditionField;
    }

    public FieldType getConditionType() {
        return conditionType;
    }

    public void setConditionType(FieldType conditionType) {
        this.conditionType = conditionType;
    }

    public String getSegmentReg()
    {
        return segmentReg;
    }

    public void setSegmentReg(String segmentReg)
    {
        this.segmentReg = segmentReg;
    }

    public String getSegmentField()
    {
        return segmentField;
    }

    public void setSegmentField(String segmentField)
    {
        this.segmentField = segmentField;
    }

    public String getIp() {
        return ip;
    }

    public void setIp(String ip) {
        this.ip = ip;
    }


    public void setPrefix(String prefix) {
        this.prefix = prefix;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUtcFields() {
        return utcFields;
    }

    public void setUtcFields(String utcFields) {
        this.utcFields = utcFields;
    }

    public String getUtcEXT() {
        return utcEXT;
    }

    public void setUtcEXT(String utcEXT) {
        this.utcEXT = utcEXT;
    }

    public int getQueryTotal() {
        return queryTotal;
    }

    public void setQueryTotal(int queryTotal) {
        this.queryTotal = queryTotal;
    }

    public List<String> getBillFieldList() {
        return billFieldList;
    }

    public void setBillFieldList(List<String> billFieldList) {
        this.billFieldList = billFieldList;
    }


    public String getIgnoreTotal() {
        return ignoreTotal;
    }

    public void setIgnoreTotal(String ignoreTotal) {
        this.ignoreTotal = ignoreTotal;
    }

    public String getConditionPath() {
        return conditionPath;
    }

    public void setConditionPath(String conditionPath) {
        this.conditionPath = conditionPath;
    }

    @Override
    public String toString() {
        final StringBuffer sb = new StringBuffer("BillConfig{");
        sb.append("prefix='").append(prefix).append('\'');
        sb.append(", exportTime='").append(exportTime).append('\'');
        sb.append(", exportType='").append(exportType).append('\'');
        sb.append(", ip='").append(ip).append('\'');
        sb.append(", id=").append(id);
        sb.append(", queryTotal=").append(queryTotal);
        sb.append(", querySql='").append(querySql).append('\'');
        sb.append(", tableName='").append(tableName).append('\'');
        sb.append(", pageSize=").append(pageSize);
        sb.append(", queryStart=").append(queryStart);
        sb.append(", fieldSplitStr='").append(fieldSplitStr).append('\'');
        sb.append(", lineSplitStr='").append(lineSplitStr).append('\'');
        sb.append(", partitions='").append(partitions).append('\'');
        sb.append(", billFields='").append(billFields).append('\'');
        sb.append(", billFieldList=").append(billFieldList);
        sb.append(", filePrefixName='").append(filePrefixName).append('\'');
        sb.append(", fileSuffixName='").append(fileSuffixName).append('\'');
        sb.append(", fileMaxLine=").append(fileMaxLine);
        sb.append(", fileMaxSize=").append(fileMaxSize);
        sb.append(", fileCharsetName='").append(fileCharsetName).append('\'');
        sb.append(", sumFileName='").append(sumFileName).append('\'');
        sb.append(", fileBasePath='").append(fileBasePath).append('\'');
        sb.append(", uploadType='").append(uploadType).append('\'');
        sb.append(", uploadDel='").append(uploadDel).append('\'');
        sb.append(", uploadDirectory='").append(uploadDirectory).append('\'');
        sb.append(", expressionRule='").append(expressionRule).append('\'');
        sb.append(", expressionField='").append(expressionField).append('\'');
        sb.append(", expressionFieldType='").append(expressionFieldType).append('\'');
        sb.append(", expressionValue='").append(expressionValue).append('\'');
        sb.append(", cronExpression='").append(cronExpression).append('\'');
        sb.append(", jsonField='").append(jsonField).append('\'');
        sb.append(", split=").append(split);
        sb.append(", dataSource='").append(dataSource).append('\'');
        sb.append(", userName='").append(userName).append('\'');
        sb.append(", channelCapacity='").append(channelCapacity).append('\'');
        sb.append(", compressed='").append(compressed).append('\'');
        sb.append(", fileBackupBasePath='").append(fileBackupBasePath).append('\'');
        sb.append(", conditionField='").append(conditionField).append('\'');
        sb.append(", conditionType=").append(conditionType);
        sb.append(", segmentReg='").append(segmentReg).append('\'');
        sb.append(", segmentField='").append(segmentField).append('\'');
        sb.append(", ignoreTotal='").append(ignoreTotal).append('\'');
        sb.append(", utcFields='").append(utcFields).append('\'');
        sb.append(", utcEXT='").append(utcEXT).append('\'');
        sb.append('}');
        return sb.toString();
    }
}
